package org.raftkv.raft.pb.enums;


public enum MessageType {

    /**
     * MsgHup 用于选举。<br/>
     * 如果节点是 Leader 或 Follower，则 Raft 中的 tick() 函数为 tickElection()。<br/>
     * 如果 Follower 或 Candidate 在选举超时之前未收到任何心跳信号，
     * 则它会将 MsgHup 传递给其 step() 方法，并成为（或继续保持）Candidate 以开始新的选举。
     */
    MsgHup,
    /**
     * MsgBeat 是一种内部类型，用于向 Leader 发送 MsgHeartBeat 类型的心跳信号。<br/>
     * 如果一个节点是 Leader，Raft 中的 tick() 函数为 tickHeartBeat()，并且定期向它的 Follower 发送 MsgHeartBeat 消息。
     */
    MsgBeat,
    /**
     * MsgProp 是一个建议将数据附加到其日志条目中的特殊类型。<br/>
     * 因此 send 方法覆盖 Message 的 term 为其 HardState 的 term，以避免将其本地 term 附加到 MsgProp 中。<br/>
     * 当将 MsgProp 传递给 Leader 的 step 方法时，Leader 首先调用 appendEntry 方法将 entry 附加到其日志中，然后调用 bcastAppend 方法
     * 将这些条目发送给其 Peers。<br/>
     * 当传递给 Candidate 时，MsgProp 会被丢弃。<br/>
     * 当传递给 Follower 时，MsgProp 通过 send 方法存储在 Follower 中的 msgs 中。<br/>
     * 它带有发送者的 ID，并会稍后转发给 Leader。
     */
    MsgProp,
    /**
     * MsgApp 包含要复制的日志条目。<br/>
     * Leader 调用 bcastAppend 方法，该方法会调用 sendAppend 方法，该方法以 MsgApp 类型发送即将复制的日志。<br/>
     * 当 MsgApp 传递给 Candidate 的 step 方法时，Candidate 将恢复到 Follower 状态，因为它表明有一个有效的 Leader 正在发送 MsgApp 消息。<br/>
     * Leader 和 Follower 以 MsgAppResp 类型响应此消息。
     */
    MsgApp,
    /**
     * MsgAppResp 是对 MsgApp 的响应。<br/>
     * 当 MsgApp 传递给 Candidate 或 Follower 的 step 方法时，它会调用 handleAppendEntries() 方法，该方法将 MsgAppResp 发送到 Raft。
     */
    MsgAppResp,
    /**
     * MsgVote 请求选票以进行选举。<br/>
     * 当一个节点是 Follower 或 Candidate，并且 MsgHup 传递到其 step 方法时，该节点调用 campaign 方法以使自己成为 Leader。<br/>
     * 一旦调用了 campaign 方法，该节点就成为了候选人，并向集群中的 Peer 发送 MsgVote 以请求选票。
     * <ul>
     *     <li>
     *         当 MsgVote 传递给 Follower 时，它仅为发送方投票，且必须满足如下条件：
     *         <ul>
     *             <li>发送方的最后任期大于 MsgVote 的任期。</li>
     *             <li>发送方的最后任期等于 MsgVote 的任期但发送方的最后提交索引大于或等于跟随者的最后提交索引。</li>
     *         </ul>
     *     </li>
     *     <li>
     *         当传递给 Leader 或 Candidate 的 step 方法并且消息的任期低于 Leader 或 Candidate 时，MsgVote 将被拒绝（MsgVoteResp 将返回拒绝）。<br/>
     *         如果 Leader 或 Candidate 接收到更高任期的 MsgVote，它将恢复为 Follower。<br/>
     *     </li>
     * </ul>
     */
    MsgVote,
    /**
     * MsgVoteResp 包含 MsgVote 请求的响应。<br/>
     * 当 MsgVoteResp 传递给 Candidate 时，Candidate 计算它赢得了多少选票。如果它超过了大多数（法定人数），
     * 它将成为 Leader 并调用 bcastAppend 方法。<br/>
     * 如果 Candidate 收到了大多数的否决票，它将恢复为 Follower。
     */
    MsgVoteResp,
    /**
     * MsgSnap 请求安装快照。<br/>
     * 当节点刚刚成为 Leader 或 Leader 接收到 MsgProp 消息时，它调用 bcastAppend 方法，该方法然后调用 sendAppend 方法以向每个跟随者发送消息。
     * 在 sendAppend 中，如果 Leader 无法获取任期或条目，则 Leader 通过发送 MsgSnap 类型的消息请求快照。
     */
    MsgSnap,
    /**
     * MsgHeartbeat 从 Leader 发送心跳。<br/>
     * 当 MsgHeartbeat 传递给 Candidate 并且消息的任期高于 Follower 时，Candidate 将恢复为 Follower，并从此心跳中更新其提交的索引。
     * 然后它将消息发送到其邮箱。<br/>
     * 当 MsgHeartbeat 传递到 Follower 的 step 方法并且消息的任期高于 Follower 时，跟随者将使用消息中的 ID 更新其 leader ID。
     */
    MsgHeartbeat,
    /**
     * MsgHeartbeatResp 是对 MsgHeartbeat 的响应。<br/>
     * 当 MsgHeartbeatResp 传递给 Leader 的 step 方法时，Leader 知道哪个 Follower 做出了响应。
     * 只有当 Leader 的最后提交索引大于 Follower 的匹配索引时，Leader 才会运行 sendAppend 方法。
     */
    MsgHeartbeatResp,
    /**
     * MsgUnreachable 告知请求（消息）未被传递。<br/>
     * 当 MsgUnreachable 传递到 Leader 的 step 方法时，Leader 会发现发送此 MsgUnreachable 的 Follower 无法到达，通常表示 MsgApp 已经丢失。<br/>
     * 当 Follower 的 Progress 状态为复制时，Leader 将其设置回探针状态。
     */
    MsgUnreachable,
    /**
     * MsgSnapStatus 告诉快照安装消息的结果。<br/>
     * 当 Follower 拒绝 MsgSnap 时，它表示由于网络问题导致网络层无法将快照发送给其 Follower，因此快照请求失败。
     * 然后，Leader 将 Follower 的进度视为探针。<br/>
     * 当 MsgSnap 未被拒绝时，它表示快照成功，领导者将跟随者的 Progress 设置为探针，并恢复其日志复制。
     */
    MsgSnapStatus,
    /**
     * 用于 Leader 检查集群可用性。<br/>
     * 在超过选举时间时，如果当前打开了 raft.checkQuorum 开关，那么 leader 将给自己发送一条 MsgCheckQuorum 消息。<br/>
     * 对该消息的处理是：检查集群中所有节点的状态，如果超过半数的节点都不活跃了，那么 Leader 也切换到 Follower 状态。
     */
    MsgCheckQuorum,
    MsgTransferLeader,
    MsgTimeoutNow,
    /**
     * MsgReadIndex 用于一致性读。
     */
    MsgReadIndex,
    /**
     * MsgReadIndex 的应答消息。
     */
    MsgReadIndexResp,
    /**
     * 用于两阶段的选举协议，当 Config.preVote 属性为 true 时，首先进行 PreVote（使用与常规选举相同的规则），
     * 除非 PreVote 表明竞选节点将获胜，否则不会有任何节点增加其任期号码。<br/>
     * 这将最小化分区节点重新加入集群时的干扰。
     */
    MsgPreVote,
    /**
     * MsgPreVote 的应答消息。
     *
     * @see MessageType#MsgPreVote
     */
    MsgPreVoteResp;

}
